home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / Palettes / KeyDownBrowser / KeyDownBrowser.m < prev    next >
Text File  |  1995-06-12  |  10KB  |  386 lines

  1. //---------------------------------------------------------------------------------------------------------
  2. //
  3. //    KeyDownBrowser
  4. //
  5. //    Inherits From:        NXBrowser
  6. //
  7. //    Declared In:        KeyDownBrowser.h
  8. //
  9. //    Disclaimer
  10. //
  11. //        You may freely copy, distribute and reuse this software and its
  12. //        associated documentation. I disclaim any warranty of any kind, 
  13. //        expressed or implied, as to its fitness for any particular use.
  14. //
  15. //---------------------------------------------------------------------------------------------------------
  16. #import "KeyDownBrowser.h"
  17. #import "KeyDownMatrix.h"
  18.  
  19.  
  20. #define RETURN        13
  21. #define LEFTARROW    172
  22. #define UPARROW    173
  23. #define RIGHTARROW    174
  24. #define DOWNARROW    175
  25.  
  26. #define CHUNK         64
  27.  
  28.  
  29. @implementation KeyDownBrowser
  30.  
  31. //---------------------------------------------------------------------------------------------------------
  32. //     Timed Entry Methods (Private)
  33. //---------------------------------------------------------------------------------------------------------
  34. void Search (timedEntry, now, self)
  35.     DPSTimedEntry    timedEntry;
  36.     double            now;
  37.     void*            self;
  38. {
  39.     [(id)self perform: @selector (_search)];
  40. }
  41.  
  42.  
  43. - _addTimedEntry
  44. {
  45.         timedEntry = DPSAddTimedEntry (inputTimeOut, Search, (void*) self,         NX_MODALRESPTHRESHOLD);
  46.         NXPing();
  47.         return self;
  48. }
  49.  
  50.  
  51. - _removeTimedEntry
  52. {
  53.     if ( ! timedEntry) return self;
  54.     DPSRemoveTimedEntry (timedEntry);
  55.     timedEntry = 0;
  56.     return self;
  57. }
  58.  
  59.  
  60. //---------------------------------------------------------------------------------------------------------
  61. //     Miscellaneous Methods (Private)
  62. //---------------------------------------------------------------------------------------------------------
  63. - _chunk
  64. {
  65.     //  Allocate memory for input buffer.
  66.     
  67.     if ( ! searchString)
  68.         searchString = NX_MALLOC (searchString, char, CHUNK);
  69.     else
  70.         searchString = NX_REALLOC (searchString, char, strlen(searchString) + CHUNK);
  71.         
  72.     if ( ! searchString) NXLogError ("Out of Memory in _chunk!");
  73.     return self;
  74. }
  75.  
  76.  
  77. - _selectCellInRow:(int)aRow ofMatrix:aMatrix andDoClick:(BOOL)doClick
  78. {
  79.     [aMatrix selectCellAt: aRow :0];
  80.     [aMatrix scrollCellToVisible: aRow :0];
  81.     if (doClick) [self doClick: aMatrix];
  82.     return self;
  83. }
  84.  
  85.  
  86. //---------------------------------------------------------------------------------------------------------
  87. //     Search Methods (Private)
  88. //---------------------------------------------------------------------------------------------------------
  89. - (int) _searchColumn
  90. {
  91.     //  If there is no selection within the browser, return column 0.  If there are multiple selections
  92.     //  return the current selected column.  If there is 1 selection, then if it is a leaf, return the 
  93.     //  current selected column.  If it is a branch, return the current selected column + 1.
  94.     
  95.     id    selectedCellList;
  96.     int    searchColumn = [self selectedColumn];
  97.     
  98.     if (searchColumn < 0) return 0;
  99.  
  100.     if ([self isMultipleSelectionEnabled])
  101.         {
  102.         selectedCellList = [self getSelectedCells: nil];
  103.         if ([selectedCellList count] == 1) 
  104.             if ([[selectedCellList objectAt: 0] isLeaf] == NO)
  105.                 searchColumn++;
  106.         [selectedCellList free];
  107.         return searchColumn;
  108.         }
  109.         
  110.     if ([self selectedCell])
  111.         if ([[self selectedCell] isLeaf] == NO) searchColumn++;
  112.         
  113.     return searchColumn;
  114. }
  115.  
  116.  
  117. - _search
  118. {
  119.     //  Searches current search column for first occurrence of searchString.
  120.     
  121.     int        iterator;
  122.     int        searchColumn = [self _searchColumn];
  123.     id        matrix = [self matrixInColumn: searchColumn];
  124.     id        currentCell;
  125.     BOOL    found = NO;
  126.     
  127.     [self _removeTimedEntry];
  128.  
  129.     for (iterator = 0; iterator < [matrix numRows]; iterator++)
  130.         {
  131.         currentCell = [matrix cellAt: iterator :0];
  132.         if (NXOrderStrings([currentCell stringValue], searchString, 
  133.             wantsCaseSensitiveSearch, strlen (searchString), NULL) == 0)
  134.             {
  135.             [matrix selectCellAt: -1 :-1];
  136.             [self _selectCellInRow:iterator ofMatrix:matrix andDoClick:YES];
  137.             found = YES;
  138.             break;
  139.             }
  140.         }
  141.     
  142.     if (! found) NXBeep();
  143.     memset (searchString, 0, strlen (searchString));
  144.     return self;
  145. }
  146.  
  147.  
  148. //---------------------------------------------------------------------------------------------------------
  149. //     Key Down Methods (Private)
  150. //---------------------------------------------------------------------------------------------------------
  151. - _upArrow: (NXEvent *) theEvent
  152. {
  153.     id    matrix;
  154.     int    selectedRow;
  155.     int    selectedColumn = [self selectedColumn];
  156.     
  157.     if (selectedColumn == -1) return self;
  158.     matrix = [self matrixInColumn:selectedColumn];
  159.     selectedRow = [matrix selectedRow] - 1;
  160.     if (selectedRow < 0) selectedRow = 0;
  161.     [self _selectCellInRow:selectedRow ofMatrix:matrix andDoClick:YES];
  162.     return self;
  163. }
  164.  
  165.  
  166. - _downArrow: (NXEvent *) theEvent
  167. {
  168.     id    matrix;
  169.     int    selectedRow;
  170.     int    selectedColumn = [self selectedColumn];
  171.     
  172.     if (selectedColumn == -1) return self;
  173.     matrix = [self matrixInColumn: selectedColumn];
  174.     selectedRow = [matrix selectedRow] + 1;
  175.     if (selectedRow > [matrix numRows] - 1) selectedRow = [matrix numRows] - 1;
  176.     [self _selectCellInRow:selectedRow ofMatrix:matrix andDoClick:YES];
  177.     return self;
  178. }
  179.  
  180.  
  181. - _leftArrow: (NXEvent *) theEvent
  182. {
  183.     id    matrix;
  184.     int    selectedColumn = [self selectedColumn];
  185.     
  186.     if (selectedColumn == -1) return self;
  187.     matrix = [self matrixInColumn: selectedColumn];
  188.     [self setLastColumn: selectedColumn];
  189.     [matrix selectCellAt: -1 :-1];
  190.     [matrix sendAction:action to:target];
  191.     if (selectedColumn == 0) return self;
  192.     selectedColumn -= 1;
  193.     matrix = [self matrixInColumn: selectedColumn];
  194.     if ([self firstVisibleColumn] > selectedColumn) [self scrollColumnsRightBy: 1];
  195.     [matrix scrollCellToVisible: [matrix selectedRow] :[matrix selectedCol]];
  196.     return self;
  197. }
  198.  
  199.  
  200. - _rightArrow: (NXEvent *) theEvent
  201. {
  202.     id matrix = [self matrixInColumn: ([self selectedColumn] + 1)];
  203.     if (! matrix) return self;
  204.     [self _selectCellInRow:0 ofMatrix:matrix andDoClick:YES];
  205.     return self;
  206. }
  207.  
  208.  
  209. - _return: (NXEvent *) theEvent
  210. {
  211.     int    selectedColumn = [self selectedColumn];
  212.     
  213.     if (selectedColumn == -1) return self;
  214.     [self doDoubleClick: [self matrixInColumn:selectedColumn]];
  215.     return self;
  216. }
  217.  
  218.  
  219. //---------------------------------------------------------------------------------------------------------
  220. //     Initialization
  221. //---------------------------------------------------------------------------------------------------------
  222. - initFrame: (const NXRect *) frameRect
  223. {
  224.     //  Give it default IB characteristics, set the Matrix class, enable keys.
  225.     
  226.     [super initFrame: frameRect];
  227.     [self setMatrixClass: [KeyDownMatrix class]];
  228.     [self separateColumns: YES];
  229.     [self setHorizontalScrollerEnabled: YES];
  230.     [self setEmptySelectionEnabled: YES];
  231.     [self setTitle: "KeyDownBrowser" ofColumn: 0];
  232.     [self acceptArrowKeys:YES andSendActionMessages:YES];
  233.     [self wantsCaseSensitiveSearch: NO];
  234.     [self inputTimeOut: 0.5];
  235.     [self _chunk];
  236.     memset (searchString, 0, CHUNK);
  237.     return self;
  238. }
  239.  
  240.  
  241. - free
  242. {
  243.     [self _removeTimedEntry];
  244.     if (searchString) free (searchString);
  245.     return [super free];
  246. }
  247.  
  248.  
  249. //---------------------------------------------------------------------------------------------------------
  250. //     Accessors
  251. //---------------------------------------------------------------------------------------------------------
  252. - wantsCaseSensitiveSearch: (BOOL) aFlag
  253. {
  254.     wantsCaseSensitiveSearch = aFlag;
  255.     return self;
  256. }
  257.  
  258.  
  259. - (BOOL) wantsCaseSensitiveSearch
  260. {
  261.     return wantsCaseSensitiveSearch;
  262. }
  263.  
  264.  
  265. - inputTimeOut: (float) aFloat
  266. {
  267.     inputTimeOut = aFloat;
  268.     return self;
  269. }
  270.  
  271.  
  272. - (float) inputTimeOut
  273. {
  274.     return inputTimeOut;
  275. }
  276.  
  277.  
  278. //---------------------------------------------------------------------------------------------------------
  279. //     Event Handling
  280. //---------------------------------------------------------------------------------------------------------
  281. - mouseDown: (NXEvent*) theEvent
  282. {
  283.     if ([self isEnabled] == NO) return self;
  284.     [super mouseDown: theEvent];
  285.     [[self window] makeFirstResponder: self] ;
  286.     return self;
  287. }
  288.  
  289.  
  290. - keyDown: (NXEvent *) theEvent
  291. {
  292.     if ([self isEnabled] == NO) return self;
  293.         
  294.     [self _removeTimedEntry];
  295.  
  296.     switch (theEvent->data.key.charCode)
  297.         {
  298.         case UPARROW:
  299.             [self _upArrow: theEvent];
  300.             break;
  301.         case DOWNARROW:
  302.             [self _downArrow: theEvent];
  303.             break;
  304.         case LEFTARROW:
  305.             [self _leftArrow: theEvent];
  306.             break;
  307.         case RIGHTARROW:
  308.             [self _rightArrow: theEvent];
  309.             break;
  310.         case RETURN:
  311.             [self _return: theEvent];
  312.             break;
  313.         default:
  314.             if (theEvent->data.key.repeat) return self;
  315.             sprintf (searchString, "%s%c", searchString, theEvent->data.key.charCode);
  316.             if (! (strlen (searchString) % (CHUNK - 1))) [self _chunk];
  317.             [self _addTimedEntry];
  318.             break;
  319.         }
  320.         
  321.     return self;
  322. }
  323.  
  324.  
  325. - (BOOL)acceptsFirstResponder
  326. {
  327.     return YES;
  328. }
  329.  
  330.  
  331. //----------------------------------------------------------------------------------------------------
  332. //    Archiving Methods
  333. //----------------------------------------------------------------------------------------------------
  334. - read: (NXTypedStream*) stream
  335. {
  336.     [super read: stream];
  337.     NXReadTypes (stream, "cf", &wantsCaseSensitiveSearch, &inputTimeOut);
  338.     return self;
  339. }
  340.  
  341.  
  342. - write: (NXTypedStream*) stream
  343. {
  344.     [super write: stream];
  345.     NXWriteTypes (stream, "cf", &wantsCaseSensitiveSearch, &inputTimeOut);
  346.     return self;
  347. }
  348.  
  349.  
  350. - awake
  351. {
  352.     [super awake];
  353.     [self _chunk];
  354.     memset (searchString, 0, CHUNK);
  355.     return self;
  356. }
  357.  
  358.  
  359. //----------------------------------------------------------------------------------------------------
  360. //    Superclass Overrides
  361. //----------------------------------------------------------------------------------------------------
  362. - acceptArrowKeys:(BOOL)acceptFlag andSendActionMessages:(BOOL)sendFlag
  363. {
  364.     [super acceptArrowKeys:YES andSendActionMessages:sendFlag];
  365.     return self;
  366. }
  367.  
  368.  
  369. - acceptArrowKeys:(BOOL)acceptFlag
  370. {
  371.     //  2.1 method.
  372.     [super acceptArrowKeys:YES andSendActionMessages:YES];
  373.     return self;
  374. }
  375.  
  376.  
  377. //---------------------------------------------------------------------------------------------------------
  378. //     IB Methods
  379. //---------------------------------------------------------------------------------------------------------
  380. - (const char*) getInspectorClassName
  381. {
  382.     return "KeyDownBrowserInspector";
  383. }
  384.  
  385.  
  386. @end